package com.qjc.interceptor.ip;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.data.redis.core.script.RedisScript;
import org.springframework.data.redis.support.atomic.RedisAtomicLong;
import org.springframework.stereotype.Component;

import java.util.Collections;
import java.util.concurrent.TimeUnit;

/**
 * @package: com.shuyu.blog.util
 * @className: RedisUtil
 * @description:
 * @author: Shuyu.Wang
 * @since: 0.1
 **/
@Component
@Slf4j
public class RedisUtil {

    private static final Long SUCCESS = 1L;

    @Autowired
    private RedisTemplate<String, Object> redisTemplate;
    // =============================common============================

    /**
     * 获取锁
     * @param lockKey
     * @param value
     * @param expireTime：单位-秒
     * @return
     */
    public boolean getLock(String lockKey, Object value, int expireTime) {
        try {
            log.info("添加分布式锁key={},expireTime={}",lockKey,expireTime);
            String script = "if redis.call('setNx',KEYS[1],ARGV[1]) then if redis.call('get',KEYS[1])==ARGV[1] then return redis.call('expire',KEYS[1],ARGV[2]) else return 0 end end";
            RedisScript<String> redisScript = new DefaultRedisScript<>(script, String.class);
            Object result = redisTemplate.execute(redisScript, Collections.singletonList(lockKey), value, expireTime);
            if (SUCCESS.equals(result)) {
                return true;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return false;
    }

    /**
     * 释放锁
     * @param lockKey
     * @param value
     * @return
     */
    public boolean releaseLock(String lockKey, String value) {
        String script = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end";
        RedisScript<String> redisScript = new DefaultRedisScript<>(script, String.class);
        Object result = redisTemplate.execute(redisScript, Collections.singletonList(lockKey), value);
        if (SUCCESS.equals(result)) {
            return true;
        }
        return false;
    }

    public boolean hasKey(String key) {
        Boolean aBoolean = redisTemplate.hasKey(key);
        return aBoolean;
    }

    public Long incr(String key, long liveTime) {
        RedisAtomicLong entityIdCounter = new RedisAtomicLong(key, redisTemplate.getConnectionFactory());
        Long increment = entityIdCounter.getAndIncrement();

        if ((null == increment || increment.longValue() == 0) && liveTime > 0) {//初始设置过期时间
            entityIdCounter.expire(liveTime, TimeUnit.SECONDS);
        }
        return increment;
    }

//
//    public static void main(String[] args) {
//        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring-redis.xml");
//        redisTemplate = applicationContext.getBean(RedisTemplate.class);
//        //设值
//        redisTemplate.opsForValue().set("i", "10");
//        print();
//        //加1
//        redisTemplate.getConnectionFactory().getConnection().incr(
//                redisTemplate.getKeySerializer().serialize("i")
//        );
//        //加4
//        redisTemplate.getConnectionFactory().getConnection().incrBy(
//                redisTemplate.getKeySerializer().serialize("i"), 4
//        );
//        print();
//        //
//        //减1
//        redisTemplate.getConnectionFactory().getConnection().decr(
//                redisTemplate.getKeySerializer().serialize("i")
//        );
//        //减4
//        redisTemplate.getConnectionFactory().getConnection().decrBy(
//                redisTemplate.getKeySerializer().serialize("i"), 4
//        );
//        print();
//        print();
//
//        //加2.3 increment是float类型
//        redisTemplate.opsForValue().increment("i",2.3);
//        print();
//    }
//    //打印
//    public static void print(){
//        System.out.println(redisTemplate.opsForValue().get("i"));
//    }
}